home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-02-15 | 48.5 KB | 1,639 lines | [TEXT/CWIE] |
- ///--------------------------------------------------------------------------------------
- // Circular Scrolling.c
- //
- // By: Vern Jensen
- //
- // Created: 7/20/96
- //
- // Description: Routines that enable you to wrap around while scrolling
- //
- // Implementation note: Unlike the standard scrolling engine, Sprites and the visScrollRect
- // in this engine will only hang off the right and bottom edges of the offscreen area when
- // wrapping, not the top and left. This was done to simplify the code in various sections.
- // It could be done in the standard scrolling engine as well if we want.
- //
- // As for how the engine works, it first clips the visScrollRect with the circular world's
- // bounds, wraps each part, and calls a function to draw the sprites in each part. This
- // function clips each sprite with the circular world's bounds, and draws each part,
- // clipping it to the current piece of the visScrollRect it's being drawn in. It may sound
- // complex, but it's the only way to do it without running into other problems.
- ///--------------------------------------------------------------------------------------
-
-
-
- #ifndef __QUICKDRAW__
- #include <QuickDraw.h>
- #endif
-
- #ifndef __MEMORY__
- #include <Memory.h>
- #endif
-
- #ifndef __GESTALT__
- #include <Gestalt.h>
- #endif
-
- #ifndef __SPRITEWORLD__
- #include "SpriteWorld.h"
- #endif
-
- #ifndef __SPRITEWORLDUTILS__
- #include "SpriteWorldUtils.h"
- #endif
-
- #ifndef __BLITPIXIE__
- #include "BlitPixie.h"
- #endif
-
- #ifndef __SCROLLING__
- #include "Scrolling.h"
- #endif
-
- #ifndef __TILING__
- #include "Tiling.h"
- #endif
-
- #ifndef __CIRCULARSCROLLING__
- #include "Circular Scrolling.h"
- #endif
-
-
- extern SpritePtr gCurrentSpriteBeingDrawn;
-
-
- ///--------------------------------------------------------------------------------------
- // SWUpdateCircularSpriteWorld
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWUpdateCircularSpriteWorld(
- SpriteWorldPtr spriteWorldP)
- {
- GWorldPtr saveGWorld;
- GDHandle saveGDH;
-
- SW_ASSERT(spriteWorldP != NULL);
- SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
- SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
-
- GetGWorld( &saveGWorld, &saveGDH );
-
- // Copy the background into the work area
- SetGWorld(spriteWorldP->workFrameP->framePort, nil);
- (*spriteWorldP->offscreenDrawProc)(spriteWorldP->backFrameP,
- spriteWorldP->workFrameP,
- &spriteWorldP->backFrameP->frameRect,
- &spriteWorldP->workFrameP->frameRect);
-
-
- spriteWorldP->frameHasOccurred = true;
- SWAnimateCircularSpriteWorld(spriteWorldP);
-
- SetGWorld( saveGWorld, saveGDH );
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWProcessCircularSpriteWorld
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWProcessCircularSpriteWorld(
- SpriteWorldPtr spriteWorldP)
- {
- register SpriteLayerPtr curSpriteLayerP;
- register SpritePtr curSpriteP;
- Rect moveBounds = spriteWorldP->scrollRectMoveBounds;
-
- // Process the sprites
- SWProcessSpriteWorld(spriteWorldP);
- if ( !spriteWorldP->frameHasOccurred )
- {
- return;
- }
-
-
- // Wrap any sprites that have moved outside the scrollRectMoveBounds
- curSpriteLayerP = spriteWorldP->headSpriteLayerP;
- while (curSpriteLayerP != NULL)
- {
- curSpriteP = curSpriteLayerP->headSpriteP;
-
- while (curSpriteP != NULL)
- {
- // Wrap left or right
- if (curSpriteP->destFrameRect.left >= moveBounds.right)
- {
- curSpriteP->destFrameRect.left -= moveBounds.right;
- curSpriteP->destFrameRect.right -= moveBounds.right;
- }
- else if (curSpriteP->destFrameRect.left < moveBounds.left)
- {
- curSpriteP->destFrameRect.left += moveBounds.right;
- curSpriteP->destFrameRect.right += moveBounds.right;
- }
-
- // Wrap up or down
- if (curSpriteP->destFrameRect.top >= moveBounds.bottom)
- {
- curSpriteP->destFrameRect.top -= moveBounds.bottom;
- curSpriteP->destFrameRect.bottom -= moveBounds.bottom;
- }
- else if (curSpriteP->destFrameRect.top < moveBounds.top)
- {
- curSpriteP->destFrameRect.top += moveBounds.bottom;
- curSpriteP->destFrameRect.bottom += moveBounds.bottom;
- }
-
- curSpriteP = curSpriteP->nextSpriteP;
- }
-
- curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
- }
-
-
- // Call the scrolling world move proc
- if (spriteWorldP->worldMoveProc != NULL)
- {
- (*spriteWorldP->worldMoveProc)(spriteWorldP, spriteWorldP->followSpriteP);
- }
-
-
- // Move visScrollRect
- if (spriteWorldP->horizScrollDelta || spriteWorldP->vertScrollDelta)
- {
- SWOffsetCircularVisScrollRect(spriteWorldP,
- spriteWorldP->horizScrollDelta,
- spriteWorldP->vertScrollDelta);
- }
- }
-
-
- // Variables shared by SWAnimateCircularSpriteWorld and SWErasePieceOfSprite.
- // These keep track of the vert and horiz scroll rect offset from the previous frame.
- short gOldVertScrollRectOffset, gOldHorizScrollRectOffset;
-
- // Variables shared by SWAnimateCircularSpriteWorld and SWDrawTilesInWrappedRect.
- // These store the original values of the named variables, so the named variables can
- // temporarily be changed and restored.
- short gTempHorizScrollRectOffset, gTempVertScrollRectOffset;
- short gTempOldVertScrollRectOffset, gTempOldHorizScrollRectOffset;
-
-
- ///--------------------------------------------------------------------------------------
- // SWAnimateCircularSpriteWorld
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWAnimateCircularSpriteWorld(
- SpriteWorldPtr spriteWorldP)
- {
- UpdateRectStructPtr curRectStructP,
- nextRectStructP;
- register SpriteLayerPtr curSpriteLayerP;
- register SpritePtr curSpriteP;
- Rect *moveBounds = &spriteWorldP->scrollRectMoveBounds;
- Rect rectA, rectB, rectC, rectD, tempDstRect;
- Boolean horizClip, vertClip;
-
- SW_ASSERT(spriteWorldP != NULL);
- SW_ASSERT(spriteWorldP->backFrameP->isFrameLocked);
- SW_ASSERT(spriteWorldP->workFrameP->isFrameLocked);
- SW_ASSERT(spriteWorldP->windowFrameP->isFrameLocked);
-
- if (!spriteWorldP->frameHasOccurred)
- return;
-
-
- // Add the deadSpriteLayer if there are any Sprites in it.
- if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
- {
- SWAddSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
- }
-
-
- gOldVertScrollRectOffset = spriteWorldP->backRect.bottom *
- (spriteWorldP->oldVisScrollRect.top / spriteWorldP->backRect.bottom);
-
- gOldHorizScrollRectOffset = spriteWorldP->backRect.right *
- (spriteWorldP->oldVisScrollRect.left / spriteWorldP->backRect.right);
-
- gTempHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
- gTempVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
- gTempOldVertScrollRectOffset = gOldVertScrollRectOffset;
- gTempOldHorizScrollRectOffset = gOldHorizScrollRectOffset;
-
-
- // Set the port to the work area so we can draw in it
- SetGWorld(spriteWorldP->workFrameP->framePort, nil);
-
-
- // Update the tiles as we scroll
- SWDrawTilesInCircularScrollRect(spriteWorldP);
-
-
- //-----------------erase the sprites--------------------
-
- rectA = spriteWorldP->oldVisScrollRect;
-
- // Wrap right side to the left
- if (rectA.right > moveBounds->right)
- {
- rectB.top = rectA.top;
- rectB.bottom = rectA.bottom;
- rectB.left = moveBounds->left;
- rectB.right = rectA.right - moveBounds->right;
-
- rectA.right = moveBounds->right;
- horizClip = true;
- }
- else
- horizClip = false;
-
-
- // Wrap bottom side to the top
- if (rectA.bottom > moveBounds->bottom)
- {
- rectC.left = rectA.left;
- rectC.right = rectA.right;
- rectC.top = moveBounds->top;
- rectC.bottom = rectA.bottom - moveBounds->bottom;
-
- rectA.bottom = moveBounds->bottom;
- rectB.bottom = moveBounds->bottom;;
- vertClip = true;
- }
- else
- vertClip = false;
-
-
- SWEraseSpritesInRect(spriteWorldP, &rectA);
-
- if (horizClip)
- {
- gOldHorizScrollRectOffset = 0; // Draw the sprites at the left of the world
- SWEraseSpritesInRect(spriteWorldP, &rectB);
- gOldHorizScrollRectOffset = gTempOldHorizScrollRectOffset;
- }
-
- if (vertClip)
- {
- gOldVertScrollRectOffset = 0; // Draw the sprites at the top of the world
- SWEraseSpritesInRect(spriteWorldP, &rectC);
- gOldVertScrollRectOffset = gTempOldVertScrollRectOffset;
- }
-
- // Wrap the corner piece
- if (vertClip && horizClip)
- {
- rectD.left = rectB.left;
- rectD.right = rectB.right;
- rectD.top = rectC.top;
- rectD.bottom = rectC.bottom;
-
- gOldVertScrollRectOffset = 0; // Draw the sprites at the top of the world
- gOldHorizScrollRectOffset = 0; // Draw the sprites at the left of the world
-
- SWEraseSpritesInRect(spriteWorldP, &rectD);
-
- gOldHorizScrollRectOffset = gTempOldHorizScrollRectOffset;
- gOldVertScrollRectOffset = gTempOldVertScrollRectOffset;
- }
-
-
- // update flagged background rects
- curRectStructP = spriteWorldP->headUpdateRectP;
- while ( curRectStructP != NULL )
- {
- tempDstRect = curRectStructP->updateRect;
-
- // Make the rect local to the offscreen area
- tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
- tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
- tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
- tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
-
- // We're not really erasing a sprite, just copying while wrapping
- SWEraseWrappedSprite(spriteWorldP, &tempDstRect);
- curRectStructP = curRectStructP->nextRectStructP;
- }
-
- // Call the postEraseCallBack
- if (spriteWorldP->postEraseCallBack != NULL)
- (*spriteWorldP->postEraseCallBack)(spriteWorldP);
-
-
-
- //-----------------draw the sprites-------------------
-
- rectA = spriteWorldP->visScrollRect;
-
- // wrap right side to the left
- if (rectA.right > moveBounds->right)
- {
- rectB.top = rectA.top;
- rectB.bottom = rectA.bottom;
- rectB.left = moveBounds->left;
- rectB.right = rectA.right - moveBounds->right;
-
- rectA.right = moveBounds->right;
- horizClip = true;
- }
- else
- horizClip = false;
-
-
- // Wrap bottom side to the top
- if (rectA.bottom > moveBounds->bottom)
- {
- rectC.left = rectA.left;
- rectC.right = rectA.right;
- rectC.top = moveBounds->top;
- rectC.bottom = rectA.bottom - moveBounds->bottom;
-
- rectA.bottom = moveBounds->bottom;
- rectB.bottom = moveBounds->bottom;
- vertClip = true;
- }
- else
- vertClip = false;
-
-
- SWDrawSpritesInRect(spriteWorldP, &rectA);
-
- if (horizClip)
- {
- spriteWorldP->horizScrollRectOffset = 0; // Draw the sprites at the left of the world
- SWDrawSpritesInRect(spriteWorldP, &rectB);
- spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
- }
-
- if (vertClip)
- {
- spriteWorldP->vertScrollRectOffset = 0; // Draw the sprites at the top of the world
- SWDrawSpritesInRect(spriteWorldP, &rectC);
- spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
- }
-
- // Wrap the corner piece
- if (vertClip && horizClip)
- {
- rectD.left = rectB.left;
- rectD.right = rectB.right;
- rectD.top = rectC.top;
- rectD.bottom = rectC.bottom;
-
- spriteWorldP->horizScrollRectOffset = 0; // Draw the sprites at the left of the world
- spriteWorldP->vertScrollRectOffset = 0; // Draw the sprites at the top of the world
-
- SWDrawSpritesInRect(spriteWorldP, &rectD);
-
- spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
- spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
- }
-
-
- // Clean up //
-
- curSpriteLayerP = spriteWorldP->headSpriteLayerP;
-
- // iterate through the layers in this world
- while (curSpriteLayerP != NULL)
- {
- curSpriteP = curSpriteLayerP->headSpriteP;
-
- // iterate through the sprites in this layer
- while (curSpriteP != NULL)
- {
- // Set last rect to current rect
- curSpriteP->oldFrameRect = curSpriteP->destFrameRect;
-
- curSpriteP->needsToBeDrawn = false;
- curSpriteP->needsToBeErased = false;
-
- curSpriteP = curSpriteP->nextSpriteP;
- }
-
- curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
- }
-
- spriteWorldP->oldVisScrollRect = spriteWorldP->visScrollRect;
-
-
- // Call the postDrawCallBack
- if (spriteWorldP->postDrawCallBack != NULL)
- (*spriteWorldP->postDrawCallBack)(spriteWorldP);
-
-
- //-----------------update the screen--------------------
-
- // Set the port to the window
- SetGWorld(spriteWorldP->windowFrameP->framePort, nil);
-
- if (spriteWorldP->usingVBL)
- {
- spriteWorldP->vblTaskRec.hasVBLFired = false;
- while ( !spriteWorldP->vblTaskRec.hasVBLFired )
- {}
- }
-
- // Copy offscreen area to screen while wrapping
- SWWrapWorldToScreen(spriteWorldP);
-
-
- // dispose of flagged background rects
- nextRectStructP = spriteWorldP->headUpdateRectP;
- while ( nextRectStructP != NULL )
- {
- curRectStructP = nextRectStructP;
- nextRectStructP = curRectStructP->nextRectStructP;
- DisposePtr( (Ptr)curRectStructP );
- }
- spriteWorldP->headUpdateRectP = NULL;
-
- spriteWorldP->numTilesChanged = 0;
-
-
- // Remove the deadSpriteLayer if we added it earlier.
- if ( spriteWorldP->deadSpriteLayerP->headSpriteP != NULL )
- {
- SWRemoveSpriteLayer(spriteWorldP, spriteWorldP->deadSpriteLayerP);
- }
- }
-
-
- #pragma mark -
- ///--------------------------------------------------------------------------------------
- // SWDrawTilesInCircularScrollRect - called by SWAnimateCircularSpriteWorld to update
- // the portion of the visScrollRect that just scrolled into view.
- ///--------------------------------------------------------------------------------------
-
- void SWDrawTilesInCircularScrollRect(
- SpriteWorldPtr spriteWorldP)
- {
- Rect tempDstRect;
- short distA, distB;
- short hScrollDelta, vScrollDelta;
-
- // Calculate the scrollDelta of the visScrollRect. Since it maybe have
- // wrapped around since the previous frame, we must go through some extra
- // hoops to make sure we calculate the delta correctly.
- distA = spriteWorldP->visScrollRect.left - spriteWorldP->oldVisScrollRect.left;
- if (distA < 0) // if (visScrollRect.left < oldVisScrollRect.left)
- distB = distA + spriteWorldP->scrollRectMoveBounds.right;
- else
- distB = distA - spriteWorldP->scrollRectMoveBounds.right;
-
- if ( SW_ABS(distB) < SW_ABS(distA) )
- hScrollDelta = distB;
- else
- hScrollDelta = distA;
-
- // Do the same for the vScrollDelta...
- distA = spriteWorldP->visScrollRect.top - spriteWorldP->oldVisScrollRect.top;
- if (distA < 0) // if (visScrollRect.top < oldVisScrollRect.top)
- distB = distA + spriteWorldP->scrollRectMoveBounds.bottom;
- else
- distB = distA - spriteWorldP->scrollRectMoveBounds.bottom;
-
- if ( SW_ABS(distB) < SW_ABS(distA) )
- vScrollDelta = distB;
- else
- vScrollDelta = distA;
-
-
- // Update tiles as we scroll if tiling is turned on
- if (spriteWorldP->tilingIsOn)
- {
- // VisScrollRect moved horizontally
- if (hScrollDelta)
- {
- // Get rect of new vertical section to update
- tempDstRect = spriteWorldP->visScrollRect;
-
- if (hScrollDelta < 0)
- tempDstRect.right = tempDstRect.left - hScrollDelta; // Moved left
- else
- tempDstRect.left = tempDstRect.right - hScrollDelta; // Moved right
-
- SWDrawTilesInWrappedRect(spriteWorldP, &tempDstRect, true);
-
-
- // Did VisScrollRect moved diagonally?
- if (vScrollDelta)
- {
- // Get rect of new horizontal section to update
- tempDstRect = spriteWorldP->visScrollRect;
-
- if (vScrollDelta < 0)
- tempDstRect.bottom = tempDstRect.top - vScrollDelta; // Moved up
- else
- tempDstRect.top = tempDstRect.bottom - vScrollDelta; // Moved down
-
- // Clip off the part we've already updated
- if (hScrollDelta < 0)
- tempDstRect.left -= hScrollDelta;
- else
- tempDstRect.right -= hScrollDelta;
-
- // We pass false here to avoid a bug which occured in the
- // tile optimizing code when updating tiles twice in one frame
- if (tempDstRect.right > tempDstRect.left)
- {
- SWDrawTilesInWrappedRect(spriteWorldP, &tempDstRect, false);
- }
- }
- } // VisScrollRect moved vertically only (not diagonally)
- else if (vScrollDelta)
- {
- // Get rect of new horizontal section to update
- tempDstRect = spriteWorldP->visScrollRect;
-
- if (vScrollDelta < 0)
- tempDstRect.bottom = tempDstRect.top - vScrollDelta; // Moved up
- else
- tempDstRect.top = tempDstRect.bottom - vScrollDelta; // Moved down
-
- SWDrawTilesInWrappedRect(spriteWorldP, &tempDstRect, true);
- }
- }
- }
-
- ///--------------------------------------------------------------------------------------
- // SWDrawTilesInWrappedRect - called by SWDrawTilesInCircularScrollRect. This function
- // draws the tiles in the rect, while wrapping the rect around the circular world's
- // bounds if it is hanging off the edge of the circular world.
- ///--------------------------------------------------------------------------------------
-
- void SWDrawTilesInWrappedRect(
- SpriteWorldPtr spriteWorldP,
- Rect* tempDstRectP,
- Boolean optimizingMode)
- {
- Rect* backRectP = &spriteWorldP->scrollRectMoveBounds;
- Rect rectA, rectB, rectC, rectD;
- Boolean horizClip, vertClip;
-
-
- rectA = *tempDstRectP;
-
-
- // Clip and wrap left or right side
- if (rectA.right > backRectP->right)
- {
- // wrap right side to the left
- rectB = rectA;
-
- if (rectB.left < backRectP->right)
- rectB.left = backRectP->right;
-
- rectB.left -= backRectP->right;
- rectB.right -= backRectP->right;
-
- rectA.right = backRectP->right;
- horizClip = true;
- }
- else
- horizClip = false;
-
-
- if (rectA.bottom > backRectP->bottom)
- {
- // wrap bottom side to the top
- rectC = rectA;
-
- if (rectC.top < backRectP->bottom)
- rectC.top = backRectP->bottom;
-
- rectC.top -= backRectP->bottom;
- rectC.bottom -= backRectP->bottom;
-
- rectA.bottom = backRectP->bottom;
- rectB.bottom = backRectP->bottom;
- vertClip = true;
- }
- else
- vertClip = false;
-
-
- if ( (rectA.bottom > rectA.top) && (rectA.right > rectA.left) )
- {
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectA, optimizingMode);
- SWWrapRectToWorkArea(spriteWorldP, &rectA);
- }
-
- if (horizClip)
- {
- spriteWorldP->horizScrollRectOffset = 0; // Draw the tiles at the left of the world
-
- if ( (rectB.bottom > rectB.top) && (rectB.right > rectB.left) )
- {
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectB, optimizingMode);
- SWWrapRectToWorkArea(spriteWorldP, &rectB);
- }
-
- spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
- }
-
- if (vertClip)
- {
- spriteWorldP->vertScrollRectOffset = 0; // Draw the tiles at the top of the world
-
- if ( (rectC.bottom > rectC.top) && (rectC.right > rectC.left) )
- {
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectC, optimizingMode);
- SWWrapRectToWorkArea(spriteWorldP, &rectC);
- }
-
- spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
- }
-
- // Wrap the corner piece
- if (vertClip && horizClip)
- {
- rectD.left = rectB.left;
- rectD.right = rectB.right;
- rectD.top = rectC.top;
- rectD.bottom = rectC.bottom;
-
- spriteWorldP->horizScrollRectOffset = 0; // Draw the tiles at the left of the world
- spriteWorldP->vertScrollRectOffset = 0; // Draw the tiles at the top of the world
-
- if ( (rectD.bottom > rectD.top) && (rectD.right > rectD.left) )
- {
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectD, optimizingMode);
- SWWrapRectToWorkArea(spriteWorldP, &rectD);
- }
-
- spriteWorldP->vertScrollRectOffset = gTempVertScrollRectOffset;
- spriteWorldP->horizScrollRectOffset = gTempHorizScrollRectOffset;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWEraseSpritesInRect - this is called up to four times by SWAnimateCircularSpriteWorld,
- // since that function clips the visScrollRect with the scrollingWorldMoveBounds.
- // Whenever that rectangle is clipped, the sprites are erased in each piece. This is
- // what allows the sprites to wrap around the world, even when they're half on one side
- // of the world and half on another side.
- //
- // This function also handles the drawing of tiles in the updateRect as we scroll.
- ///--------------------------------------------------------------------------------------
-
- void SWEraseSpritesInRect(
- SpriteWorldPtr spriteWorldP,
- Rect* updateRectP)
- {
- register SpriteLayerPtr curSpriteLayerP;
- register SpritePtr curSpriteP;
- short curTileLayer;
- Rect dstRectA, dstRectB, dstRectC, dstRectD;
- short rightClip, bottomClip;
-
-
- //-----------------erase the sprites--------------------
-
-
- curSpriteLayerP = spriteWorldP->headSpriteLayerP;
- curTileLayer = 0;
-
- // iterate through the layers in this world
- while (curSpriteLayerP != NULL)
- {
- curSpriteP = curSpriteLayerP->headSpriteP;
-
- if (curSpriteLayerP->tileLayer > curTileLayer)
- curTileLayer = curSpriteLayerP->tileLayer;
-
- // iterate through the sprites in this layer
- while (curSpriteP != NULL)
- {
- SW_ASSERT(curSpriteP->curFrameP->isFrameLocked);
- curSpriteP->tileDepth = curTileLayer;
-
- if (curSpriteP->isVisible)
- {
- dstRectA = curSpriteP->oldFrameRect;
-
- // Here we clip the sprite with the circular world's right and bottom sides.
- // Then we clip each piece with the updateRectP and draw it.
-
- // clip off the bottom
- if (dstRectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
- {
- bottomClip = dstRectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
- dstRectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
- }
- else
- bottomClip = 0;
-
- // clip off the right
- if (dstRectA.right > spriteWorldP->scrollRectMoveBounds.right)
- {
- rightClip = dstRectA.right - spriteWorldP->scrollRectMoveBounds.right;
- dstRectA.right = spriteWorldP->scrollRectMoveBounds.right;
- }
- else
- rightClip = 0;
-
-
- // First erase the main piece of the sprite
- SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectA);
-
- if (bottomClip) // Wrap bottom piece to top
- {
- dstRectB.right = dstRectA.right;
- dstRectB.left = dstRectA.left;
- dstRectB.top = spriteWorldP->scrollRectMoveBounds.top;
- dstRectB.bottom = spriteWorldP->scrollRectMoveBounds.top + bottomClip;
-
- SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectB);
- }
-
- if (rightClip) // Wrap right piece to the left
- {
- dstRectC.top = dstRectA.top;
- dstRectC.bottom = dstRectA.bottom;
- dstRectC.left = spriteWorldP->scrollRectMoveBounds.left;
- dstRectC.right = spriteWorldP->scrollRectMoveBounds.left + rightClip;
-
- SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectC);
- }
-
- // If there is a corner piece, wrap it too.
- if (rightClip && bottomClip)
- {
- dstRectD.top = dstRectB.top;
- dstRectD.bottom = dstRectB.bottom;
- dstRectD.left = dstRectC.left;
- dstRectD.right = dstRectC.right;
-
- SWErasePieceOfSprite(spriteWorldP, updateRectP, &dstRectD);
- }
- }
-
- curSpriteP = curSpriteP->nextSpriteP;
- }
-
- curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWDrawSpritesInRect - this is called up to four times by SWAnimateCircularSpriteWorld,
- // since that function clips the visScrollRect with the scrollingWorldMoveBounds.
- // Whenever that rectangle is clipped, the sprites are drawn in each piece. This is
- // what allows the sprites to wrap around the world, even when they're half on one side
- // of the world and half on another side.
- ///--------------------------------------------------------------------------------------
-
- void SWDrawSpritesInRect(
- SpriteWorldPtr spriteWorldP,
- Rect* updateRectP)
- {
- register SpriteLayerPtr curSpriteLayerP;
- register SpritePtr curSpriteP;
- Rect srcRectA, srcRectB, srcRectC, srcRectD;
- Rect dstRectA, dstRectB, dstRectC, dstRectD;
- short rightClip, bottomClip;
-
-
- curSpriteLayerP = spriteWorldP->headSpriteLayerP;
-
- // iterate through the layers in this world
- while (curSpriteLayerP != NULL)
- {
- curSpriteP = curSpriteLayerP->headSpriteP;
-
- // iterate through the sprites in this layer
- while (curSpriteP != NULL)
- {
- if (curSpriteP->isVisible)
- {
- srcRectA = curSpriteP->curFrameP->frameRect;
- dstRectA = curSpriteP->destFrameRect;
-
- // Here we clip the sprite with the circular world's bounds. Then
- // we clip each piece with the updateRectP and draw it.
-
- // clip off the bottom
- if (dstRectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
- {
- bottomClip = dstRectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
- dstRectA.bottom -= bottomClip;
- srcRectA.bottom -= bottomClip;
- }
- else
- bottomClip = 0;
-
- // clip off the right
- if (dstRectA.right > spriteWorldP->scrollRectMoveBounds.right)
- {
- rightClip = dstRectA.right - spriteWorldP->scrollRectMoveBounds.right;
- dstRectA.right -= rightClip;
- srcRectA.right -= rightClip;
- }
- else
- rightClip = 0;
-
- // First draw the main piece of the sprite
- SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP,
- &srcRectA, &dstRectA);
-
- // Now we wrap any pieces that are hanging off the border of
- // the circular scrolling world. (Which were clipped above.)
-
- if (bottomClip) // Wrap bottom piece to top
- {
- dstRectB.right = dstRectA.right;
- dstRectB.left = dstRectA.left;
- dstRectB.top = spriteWorldP->scrollRectMoveBounds.top;
- dstRectB.bottom = spriteWorldP->scrollRectMoveBounds.top + bottomClip;
-
- srcRectB = srcRectA;
- srcRectB.bottom += bottomClip;
- srcRectB.top += SW_RECT_HEIGHT(dstRectA);
-
- SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP,
- &srcRectB, &dstRectB);
- }
-
- if (rightClip) // Wrap right piece to the left
- {
- dstRectC.top = dstRectA.top;
- dstRectC.bottom = dstRectA.bottom;
- dstRectC.left = spriteWorldP->scrollRectMoveBounds.left;
- dstRectC.right = spriteWorldP->scrollRectMoveBounds.left + rightClip;
-
- srcRectC = srcRectA;
- srcRectC.right += rightClip;
- srcRectC.left += SW_RECT_WIDTH(dstRectA);
-
- SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP,
- &srcRectC, &dstRectC);
- }
-
- // If there is a corner piece, wrap it too.
- if (rightClip && bottomClip)
- {
- dstRectD.top = dstRectB.top;
- dstRectD.bottom = dstRectB.bottom;
- dstRectD.left = dstRectC.left;
- dstRectD.right = dstRectC.right;
-
- srcRectD.top = srcRectB.top;
- srcRectD.bottom = srcRectB.bottom;
- srcRectD.left = srcRectC.left;
- srcRectD.right = srcRectC.right;
-
- SWDrawPieceOfSprite(spriteWorldP, updateRectP, curSpriteP,
- &srcRectD, &dstRectD);
- }
- }
-
- curSpriteP = curSpriteP->nextSpriteP;
- }
-
- curSpriteLayerP = curSpriteLayerP->nextSpriteLayerP;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWErasePieceOfSprite
- ///--------------------------------------------------------------------------------------
-
- void SWErasePieceOfSprite(
- SpriteWorldPtr spriteWorldP,
- Rect* updateRectP,
- Rect* dstRectP)
- {
- Rect dstRect = *dstRectP;
- short temp;
-
- // Clip the sprite with this portion of the visScrollRect
- if (dstRect.top < updateRectP->top)
- dstRect.top = updateRectP->top;
-
- if (dstRect.bottom > updateRectP->bottom)
- dstRect.bottom = updateRectP->bottom;
-
- if (dstRect.left < updateRectP->left)
- dstRect.left = updateRectP->left;
-
- if (dstRect.right > updateRectP->right)
- dstRect.right = updateRectP->right;
-
-
- // Is the sprite visible in this rect?
- if ( (dstRect.right > dstRect.left) && (dstRect.bottom > dstRect.top) )
- {
- // Make the sprite's rect local to the offscreen area
- dstRect.top -= gOldVertScrollRectOffset;
- dstRect.bottom -= gOldVertScrollRectOffset;
- dstRect.left -= gOldHorizScrollRectOffset;
- dstRect.right -= gOldHorizScrollRectOffset;
-
- // align the left edge to long word boundary
- dstRect.left &= (spriteWorldP->workFrameP->leftAlignFactor);
-
- // align the right edge to long word boundary
- temp = dstRect.right & spriteWorldP->workFrameP->rightAlignFactor;
-
- if (temp != 0)
- dstRect.right += (spriteWorldP->workFrameP->rightAlignFactor + 1) - temp;
-
- SWEraseWrappedSprite(spriteWorldP, &dstRect);
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWDrawPieceOfSprite
- ///--------------------------------------------------------------------------------------
-
- void SWDrawPieceOfSprite(
- SpriteWorldPtr spriteWorldP,
- Rect* updateRectP,
- SpritePtr curSpriteP,
- Rect* srcRectP,
- Rect* dstRectP)
- {
- Rect srcRect = *srcRectP;
- Rect dstRect = *dstRectP;
- Rect tempDstRect;
-
- // Clip the sprite with this portion of the visScrollRect
- if (dstRect.top < updateRectP->top)
- {
- srcRect.top += updateRectP->top - dstRect.top;
- dstRect.top = updateRectP->top;
- }
-
- if (dstRect.bottom > updateRectP->bottom)
- {
- srcRect.bottom += updateRectP->bottom - dstRect.bottom;
- dstRect.bottom = updateRectP->bottom;
- }
-
- if (dstRect.left < updateRectP->left)
- {
- srcRect.left += updateRectP->left - dstRect.left;
- dstRect.left = updateRectP->left;
- }
-
- if (dstRect.right > updateRectP->right)
- {
- srcRect.right += updateRectP->right - dstRect.right;
- dstRect.right = updateRectP->right;
- }
-
-
- // Is the sprite visible in this rect?
- if ( (dstRect.right > dstRect.left) && (dstRect.bottom > dstRect.top) )
- {
- gCurrentSpriteBeingDrawn = curSpriteP;
-
- // Make the sprite's rect local to the offscreen area
- tempDstRect = dstRect;
- tempDstRect.top -= spriteWorldP->vertScrollRectOffset;
- tempDstRect.bottom -= spriteWorldP->vertScrollRectOffset;
- tempDstRect.left -= spriteWorldP->horizScrollRectOffset;
- tempDstRect.right -= spriteWorldP->horizScrollRectOffset;
-
- SWDrawWrappedSprite(curSpriteP, spriteWorldP->workFrameP, &srcRect, &tempDstRect);
-
- gCurrentSpriteBeingDrawn = NULL;
-
- // Draw tiles above sprite
- if (spriteWorldP->tilingIsOn &&
- curSpriteP->tileDepth <= spriteWorldP->lastActiveTileLayer)
- {
- SWDrawTilesAboveSprite(spriteWorldP, &dstRect, curSpriteP->tileDepth);
- }
- }
- }
-
-
- #pragma mark -
- ///--------------------------------------------------------------------------------------
- // SWMoveCircularVisScrollRect
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWMoveCircularVisScrollRect(
- SpriteWorldPtr spriteWorldP,
- short horizPos,
- short vertPos)
- {
- short width, height, moveBoundsWidth, moveBoundsHeight;
-
- height = spriteWorldP->visScrollRect.bottom - spriteWorldP->visScrollRect.top;
- width = spriteWorldP->visScrollRect.right - spriteWorldP->visScrollRect.left;
-
- spriteWorldP->visScrollRect.top = vertPos;
- spriteWorldP->visScrollRect.bottom = vertPos + height;
- spriteWorldP->visScrollRect.left = horizPos;
- spriteWorldP->visScrollRect.right = horizPos + width;
-
- moveBoundsWidth = SW_RECT_WIDTH(spriteWorldP->scrollRectMoveBounds);
- moveBoundsHeight = SW_RECT_HEIGHT(spriteWorldP->scrollRectMoveBounds);
-
- // Wrap visScrollRect if it has moved past the circular world's moveBounds
- if (spriteWorldP->visScrollRect.top >= spriteWorldP->scrollRectMoveBounds.bottom)
- {
- spriteWorldP->visScrollRect.top -= moveBoundsHeight;
- spriteWorldP->visScrollRect.bottom -= moveBoundsHeight;
- }
- else if (spriteWorldP->visScrollRect.top < spriteWorldP->scrollRectMoveBounds.top)
- {
- spriteWorldP->visScrollRect.top += moveBoundsHeight;
- spriteWorldP->visScrollRect.bottom += moveBoundsHeight;
- }
-
- if (spriteWorldP->visScrollRect.left >= spriteWorldP->scrollRectMoveBounds.right)
- {
- spriteWorldP->visScrollRect.left -= moveBoundsWidth;
- spriteWorldP->visScrollRect.right -= moveBoundsWidth;
- }
- else if (spriteWorldP->visScrollRect.left < spriteWorldP->scrollRectMoveBounds.left)
- {
- spriteWorldP->visScrollRect.left += moveBoundsWidth;
- spriteWorldP->visScrollRect.right += moveBoundsWidth;
- }
-
- SWCalculateOffscreenScrollRect(spriteWorldP);
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWOffsetCircularVisScrollRect
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWOffsetCircularVisScrollRect(
- SpriteWorldPtr spriteWorldP,
- short horizOffset,
- short vertOffset)
- {
- short moveBoundsWidth, moveBoundsHeight;
-
- spriteWorldP->visScrollRect.top += vertOffset;
- spriteWorldP->visScrollRect.bottom += vertOffset;
- spriteWorldP->visScrollRect.left += horizOffset;
- spriteWorldP->visScrollRect.right += horizOffset;
-
- moveBoundsWidth = SW_RECT_WIDTH(spriteWorldP->scrollRectMoveBounds);
- moveBoundsHeight = SW_RECT_HEIGHT(spriteWorldP->scrollRectMoveBounds);
-
- // Wrap visScrollRect if it has moved past the circular world's moveBounds
- if (spriteWorldP->visScrollRect.top >= spriteWorldP->scrollRectMoveBounds.bottom)
- {
- spriteWorldP->visScrollRect.top -= moveBoundsHeight;
- spriteWorldP->visScrollRect.bottom -= moveBoundsHeight;
- }
- else if (spriteWorldP->visScrollRect.top < spriteWorldP->scrollRectMoveBounds.top)
- {
- spriteWorldP->visScrollRect.top += moveBoundsHeight;
- spriteWorldP->visScrollRect.bottom += moveBoundsHeight;
- }
-
- if (spriteWorldP->visScrollRect.left >= spriteWorldP->scrollRectMoveBounds.right)
- {
- spriteWorldP->visScrollRect.left -= moveBoundsWidth;
- spriteWorldP->visScrollRect.right -= moveBoundsWidth;
- }
- else if (spriteWorldP->visScrollRect.left < spriteWorldP->scrollRectMoveBounds.left)
- {
- spriteWorldP->visScrollRect.left += moveBoundsWidth;
- spriteWorldP->visScrollRect.right += moveBoundsWidth;
- }
-
- SWCalculateOffscreenScrollRect(spriteWorldP);
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWCollideCircularSpriteLayer - compares wrapped srcSprite with wrapped dstSprite
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWCollideCircularSpriteLayer(
- SpriteWorldPtr spriteWorldP,
- SpriteLayerPtr srcSpriteLayerP,
- SpriteLayerPtr dstSpriteLayerP)
- {
- SpritePtr srcSpriteP, nextSrcSpriteP;
- SpritePtr dstSpriteP, nextDstSpriteP;
- Rect sectRect, srcRect[4], dstRect[4];
- Boolean srcRectWrapped[4], dstRectWrapped[4];
- short srcNum, dstNum, moveBoundsWidth, moveBoundsHeight;
-
- // Don't check for collisions unless the frame has been processed!
- if (!spriteWorldP->frameHasOccurred)
- return;
-
- moveBoundsWidth = SW_RECT_WIDTH(spriteWorldP->scrollRectMoveBounds);
- moveBoundsHeight = SW_RECT_HEIGHT(spriteWorldP->scrollRectMoveBounds);
-
- srcRectWrapped[0] = true; // These values will always be true
- dstRectWrapped[0] = true;
-
- srcSpriteP = srcSpriteLayerP->headSpriteP;
-
- // Cycle through all source Sprites
- while (srcSpriteP != NULL)
- {
- // Skip this sprite if it has no collideProc
- if (srcSpriteP->spriteCollideProc == NULL)
- {
- srcSpriteP = srcSpriteP->nextSpriteP;
- continue;
- }
-
- dstSpriteP = dstSpriteLayerP->headSpriteP;
- nextSrcSpriteP = srcSpriteP->nextSpriteP;
- srcRect[0] = srcSpriteP->destFrameRect;
-
- //-----------------------Clip the source sprite-----------------------
-
- // Keeps track of which rects were given values
- srcRectWrapped[1] = srcRectWrapped[2] = srcRectWrapped[3] = false;
-
- // Wrap bottom piece to the top //
- if (srcRect[0].bottom > spriteWorldP->scrollRectMoveBounds.bottom)
- {
- srcRect[1].top = srcRect[0].top - moveBoundsHeight;
- srcRect[1].bottom = srcRect[0].bottom - moveBoundsHeight;
- srcRect[1].left = srcRect[0].left;
- srcRect[1].right = srcRect[0].right;
- srcRectWrapped[1] = true;
- }
-
- // Wrap right piece to the left //
- if (srcRect[0].right > spriteWorldP->scrollRectMoveBounds.right)
- {
- srcRect[2].top = srcRect[0].top;
- srcRect[2].bottom = srcRect[0].bottom;
- srcRect[2].left = srcRect[0].left - moveBoundsWidth;
- srcRect[2].right = srcRect[0].right - moveBoundsWidth;
- srcRectWrapped[2] = true;
- }
-
- // Wrap bottom-right piece to upper left corner //
- if (srcRectWrapped[1] && srcRectWrapped[2])
- {
- srcRect[3].top = srcRect[1].top;
- srcRect[3].bottom = srcRect[1].bottom;
- srcRect[3].left = srcRect[2].left;
- srcRect[3].right = srcRect[2].right;
- srcRectWrapped[3] = true;
- }
-
- // Cycle through all dest Sprites
- while (dstSpriteP != NULL)
- {
- nextDstSpriteP = dstSpriteP->nextSpriteP;
- dstRect[0] = dstSpriteP->destFrameRect;
-
- //-----------------------Clip the dest sprite-----------------------
-
- if (srcSpriteP != dstSpriteP)
- {
- // Keeps track of which rects were given values
- dstRectWrapped[1] = dstRectWrapped[2] = dstRectWrapped[3] = false;
-
- // Wrap bottom piece to the top //
- if (dstRect[0].bottom > spriteWorldP->scrollRectMoveBounds.bottom)
- {
- dstRect[1].top = dstRect[0].top - moveBoundsHeight;
- dstRect[1].bottom = dstRect[0].bottom - moveBoundsHeight;
- dstRect[1].left = dstRect[0].left;
- dstRect[1].right = dstRect[0].right;
- dstRectWrapped[1] = true;
- }
-
- // Wrap right piece to the left //
- if (dstRect[0].right > spriteWorldP->scrollRectMoveBounds.right)
- {
- dstRect[2].top = dstRect[0].top;
- dstRect[2].bottom = dstRect[0].bottom;
- dstRect[2].left = dstRect[0].left - moveBoundsWidth;
- dstRect[2].right = dstRect[0].right - moveBoundsWidth;
- dstRectWrapped[2] = true;
- }
-
- // Wrap bottom-right piece to upper left corner //
- if (dstRectWrapped[1] && dstRectWrapped[2])
- {
- dstRect[3].top = dstRect[1].top;
- dstRect[3].bottom = dstRect[1].bottom;
- dstRect[3].left = dstRect[2].left;
- dstRect[3].right = dstRect[2].right;
- dstRectWrapped[3] = true;
- }
-
-
- // Check for overlapping rects (compare each dstRect with each srcRect)
- for (srcNum = 0; srcNum <= 3; srcNum++)
- {
- if (srcRectWrapped[srcNum] == false)
- continue;
-
- for (dstNum = 0; dstNum <= 3; dstNum++)
- {
- if (dstRectWrapped[dstNum] == false)
- continue;
-
- if ( (srcRect[srcNum].top < dstRect[dstNum].bottom) &&
- (srcRect[srcNum].bottom > dstRect[dstNum].top) &&
- (srcRect[srcNum].left < dstRect[dstNum].right) &&
- (srcRect[srcNum].right > dstRect[dstNum].left) )
- {
- sectRect.left = SW_MAX(srcRect[srcNum].left, dstRect[dstNum].left);
- sectRect.top = SW_MAX(srcRect[srcNum].top, dstRect[dstNum].top);
- sectRect.right = SW_MIN(srcRect[srcNum].right, dstRect[dstNum].right);
- sectRect.bottom = SW_MIN(srcRect[srcNum].bottom, dstRect[dstNum].bottom);
-
- (*srcSpriteP->spriteCollideProc)(srcSpriteP, dstSpriteP, §Rect);
- }
- }
- }
- }
-
- // If the nextDstSpriteP has been removed, we must start over again
- if (nextDstSpriteP != NULL && nextDstSpriteP->spriteRemoval != kSWDontRemoveSprite)
- dstSpriteP = dstSpriteLayerP->headSpriteP;
- else
- dstSpriteP = nextDstSpriteP;
- }
-
- // If the nextSrcSpriteP has been removed, we must start over again
- if (nextSrcSpriteP != NULL && nextSrcSpriteP->spriteRemoval != kSWDontRemoveSprite)
- srcSpriteP = srcSpriteLayerP->headSpriteP;
- else
- srcSpriteP = nextSrcSpriteP;
- }
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWChangeCircularTileImage - this function simply calls SWUpdateCircularTileOnScreen
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWChangeCircularTileImage(
- SpriteWorldPtr spriteWorldP,
- short tileID,
- short newImage)
- {
- // Set the current image
- spriteWorldP->curTileImage[tileID] = newImage;
-
- // Update the tile image on screen
- SWUpdateCircularTileOnScreen(spriteWorldP, tileID);
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWUpdateCircularTileOnScreen - this is actually quite similar to SWDrawCircularTile,
- // except that it calls SWUpdateTileOnScreen instead of SWDrawTile.
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWUpdateCircularTileOnScreen(
- SpriteWorldPtr spriteWorldP,
- short tileID)
- {
- short oldHorizScrollRectOffset, oldVertScrollRectOffset;
- Rect oldVisScrollRect, rectA, rectB, rectC, rectD;
- Boolean horizClip, vertClip;
-
- oldVisScrollRect = spriteWorldP->visScrollRect;
- oldHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
- oldVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
-
- rectA = spriteWorldP->visScrollRect;
-
-
- // Wrap right side to the left
- if (rectA.right > spriteWorldP->scrollRectMoveBounds.right)
- {
- rectB.top = rectA.top;
- rectB.bottom = rectA.bottom;
- rectB.left = spriteWorldP->scrollRectMoveBounds.left;
- rectB.right = rectA.right - spriteWorldP->scrollRectMoveBounds.right;
-
- rectA.right = spriteWorldP->scrollRectMoveBounds.right;
- horizClip = true;
- }
- else
- horizClip = false;
-
-
- // Wrap bottom side to the top
- if (rectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
- {
- rectC.left = rectA.left;
- rectC.right = rectA.right;
- rectC.top = spriteWorldP->scrollRectMoveBounds.top;
- rectC.bottom = rectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
-
- rectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
- rectB.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
- vertClip = true;
- }
- else
- vertClip = false;
-
-
- // Update tiles in rectA
- spriteWorldP->visScrollRect = rectA;
- SWUpdateTileOnScreen(spriteWorldP, tileID);
-
-
- // Update tiles in rectB
- if (horizClip)
- {
- spriteWorldP->horizScrollRectOffset = 0; // Draw the tile at the left of the world
-
- spriteWorldP->visScrollRect = rectB;
- SWUpdateTileOnScreen(spriteWorldP, tileID);
-
- spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
- }
-
- // Update tiles in rectC
- if (vertClip)
- {
- spriteWorldP->vertScrollRectOffset = 0; // Draw the tile at the top of the world
-
- spriteWorldP->visScrollRect = rectC;
- SWUpdateTileOnScreen(spriteWorldP, tileID);
-
- spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
- }
-
- // Update tiles in rectD (corner piece)
- if (vertClip && horizClip)
- {
- rectD.left = rectB.left;
- rectD.right = rectB.right;
- rectD.top = rectC.top;
- rectD.bottom = rectC.bottom;
-
- spriteWorldP->horizScrollRectOffset = 0; // Draw the sprites at the left of the world
- spriteWorldP->vertScrollRectOffset = 0; // Draw the sprites at the top of the world
-
- spriteWorldP->visScrollRect = rectD;
- SWUpdateTileOnScreen(spriteWorldP, tileID);
-
- spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
- spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
- }
-
-
- // Restore visScrollRect now that we're done
- spriteWorldP->visScrollRect = oldVisScrollRect;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWDrawTilesInCircularBackground
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC OSErr SWDrawTilesInCircularBackground(
- SpriteWorldPtr spriteWorldP)
- {
- short oldHorizScrollRectOffset, oldVertScrollRectOffset;
- Rect oldVisScrollRect, rectA, rectB, rectC, rectD;
- Boolean horizClip, vertClip;
- GWorldPtr holdGWorld;
- GDHandle holdGDH;
-
- GetGWorld( &holdGWorld, &holdGDH );
-
- if ( !spriteWorldP->tilingIsInitialized )
- {
- SWSetStickyIfError(kTilingNotInitialized);
- return kTilingNotInitialized;
- }
-
-
- // Save these values so we can restore them later
- oldVisScrollRect = spriteWorldP->visScrollRect;
- oldHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
- oldVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
-
- rectA = spriteWorldP->visScrollRect;
-
-
- // Wrap right side to the left
- if (rectA.right > spriteWorldP->scrollRectMoveBounds.right)
- {
- rectB.top = rectA.top;
- rectB.bottom = rectA.bottom;
- rectB.left = spriteWorldP->scrollRectMoveBounds.left;
- rectB.right = rectA.right - spriteWorldP->scrollRectMoveBounds.right;
-
- rectA.right = spriteWorldP->scrollRectMoveBounds.right;
- horizClip = true;
- }
- else
- horizClip = false;
-
-
- // Wrap bottom side to the top
- if (rectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
- {
- rectC.left = rectA.left;
- rectC.right = rectA.right;
- rectC.top = spriteWorldP->scrollRectMoveBounds.top;
- rectC.bottom = rectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
-
- rectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
- rectB.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
- vertClip = true;
- }
- else
- vertClip = false;
-
-
- // Draw tiles in the main piece
- spriteWorldP->visScrollRect = rectA;
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectA, true);
-
-
- // Draw tile in rectB
- if (horizClip)
- {
- spriteWorldP->horizScrollRectOffset = 0; // Draw the tiles at the left of the world
-
- spriteWorldP->visScrollRect = rectB;
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectB, false);
-
- spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
- }
-
- // Draw tile in rectC
- if (vertClip)
- {
- spriteWorldP->vertScrollRectOffset = 0; // Draw the tiles at the top of the world
-
- spriteWorldP->visScrollRect = rectC;
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectC, false);
-
- spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
- }
-
- // Draw tile in rectD (corner piece)
- if (vertClip && horizClip)
- {
- rectD.left = rectB.left;
- rectD.right = rectB.right;
- rectD.top = rectC.top;
- rectD.bottom = rectC.bottom;
-
- spriteWorldP->horizScrollRectOffset = 0; // Draw the sprites at the left of the world
- spriteWorldP->vertScrollRectOffset = 0; // Draw the sprites at the top of the world
-
- spriteWorldP->visScrollRect = rectD;
- (*spriteWorldP->tileRectDrawProc)(spriteWorldP, &rectD, false);
-
- spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
- spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
- }
-
- // Restore visScrollRect now that we're done
- spriteWorldP->visScrollRect = oldVisScrollRect;
-
-
- // Restore the original port
- SetGWorld( holdGWorld, holdGDH );
-
- return noErr;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // SWDrawCircularTile
- ///--------------------------------------------------------------------------------------
-
- SW_FUNC void SWDrawCircularTile(
- SpriteWorldPtr spriteWorldP,
- short dstTileLayer,
- short tileRow,
- short tileCol,
- short tileID)
- {
- short oldHorizScrollRectOffset, oldVertScrollRectOffset;
- Rect tileRect, oldVisScrollRect, rectA, rectB, rectC, rectD;
- Boolean horizClip, vertClip;
-
- // We must have a TileMap installed in the dstTileLayer to draw in it!
- if (spriteWorldP->tileLayerArray[dstTileLayer] == NULL)
- return;
-
- tileRect.top = tileRow * spriteWorldP->tileHeight;
- tileRect.left = tileCol * spriteWorldP->tileWidth;
- tileRect.bottom = tileRect.top + spriteWorldP->tileHeight;
- tileRect.right = tileRect.left + spriteWorldP->tileWidth;
-
- // Save these values so we can restore them later
- oldVisScrollRect = spriteWorldP->visScrollRect;
- oldHorizScrollRectOffset = spriteWorldP->horizScrollRectOffset;
- oldVertScrollRectOffset = spriteWorldP->vertScrollRectOffset;
-
- rectA = spriteWorldP->visScrollRect;
-
-
- // Wrap right side to the left
- if (rectA.right > spriteWorldP->scrollRectMoveBounds.right)
- {
- rectB.top = rectA.top;
- rectB.bottom = rectA.bottom;
- rectB.left = spriteWorldP->scrollRectMoveBounds.left;
- rectB.right = rectA.right - spriteWorldP->scrollRectMoveBounds.right;
-
- rectA.right = spriteWorldP->scrollRectMoveBounds.right;
- horizClip = true;
- }
- else
- horizClip = false;
-
-
- // Wrap bottom side to the top
- if (rectA.bottom > spriteWorldP->scrollRectMoveBounds.bottom)
- {
- rectC.left = rectA.left;
- rectC.right = rectA.right;
- rectC.top = spriteWorldP->scrollRectMoveBounds.top;
- rectC.bottom = rectA.bottom - spriteWorldP->scrollRectMoveBounds.bottom;
-
- rectA.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
- rectB.bottom = spriteWorldP->scrollRectMoveBounds.bottom;
- vertClip = true;
- }
- else
- vertClip = false;
-
-
- // Draw tile in rectA
- if ( SW_RECT_IS_IN_RECT(tileRect, rectA) )
- {
- spriteWorldP->visScrollRect = rectA;
- SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
- }
-
- // Draw tile in rectB
- if (horizClip)
- {
- spriteWorldP->horizScrollRectOffset = 0; // Draw the tile at the left of the world
-
- if ( SW_RECT_IS_IN_RECT(tileRect, rectB) )
- {
- spriteWorldP->visScrollRect = rectB;
- SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
- }
-
- spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
- }
-
- // Draw tile in rectC
- if (vertClip)
- {
- spriteWorldP->vertScrollRectOffset = 0; // Draw the tile at the top of the world
-
- if ( SW_RECT_IS_IN_RECT(tileRect, rectC) )
- {
- spriteWorldP->visScrollRect = rectC;
- SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
- }
-
- spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
- }
-
- // Draw tile in rectD (corner piece)
- if (vertClip && horizClip)
- {
- rectD.left = rectB.left;
- rectD.right = rectB.right;
- rectD.top = rectC.top;
- rectD.bottom = rectC.bottom;
-
- spriteWorldP->horizScrollRectOffset = 0; // Draw the sprites at the left of the world
- spriteWorldP->vertScrollRectOffset = 0; // Draw the sprites at the top of the world
-
- if ( SW_RECT_IS_IN_RECT(tileRect, rectD) )
- {
- spriteWorldP->visScrollRect = rectD;
- SWDrawTile(spriteWorldP, dstTileLayer, tileRow, tileCol, tileID);
- }
-
- spriteWorldP->vertScrollRectOffset = oldVertScrollRectOffset;
- spriteWorldP->horizScrollRectOffset = oldHorizScrollRectOffset;
- }
-
- // Put the new tileID in the TileMap (done in case the tile isn't visible in
- // any part of the visScrollRect, in which case SWDrawTile would never be called.)
- spriteWorldP->tileLayerArray[dstTileLayer]->tileMap[tileRow][tileCol] = tileID;
-
- // Restore visScrollRect now that we're done
- spriteWorldP->visScrollRect = oldVisScrollRect;
- }
-
-